package com.sap.sap_mangers.controller;

import com.sap.sap_mangers.Vo.BmsVo.BmsBorrowVo;
import com.sap.sap_mangers.Vo.BmsVo.BmsManagerVo;
import com.sap.sap_mangers.dto.bms.*;
import com.sap.sap_mangers.dto.user.NoticeDto;
import com.sap.sap_mangers.email.IMailService;
import com.sap.sap_mangers.pojo.SapBmsBook;
import com.sap.sap_mangers.pojo.SapBmsBorrow;
import com.sap.sap_mangers.pojo.User;
import com.sap.sap_mangers.service.BmsService;
import com.sap.sap_mangers.service.UserService;
import com.sap.sap_mangers.until.CommonUtils;
import com.sap.sap_mangers.until.CosUntil;
import com.sap.sap_mangers.until.JwtUtil;
import com.sap.sap_mangers.until.SimpleJson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

/**
 * @author ZhouKai
 * 2022/8/8 22:47
 */
@RestController
@RequestMapping("/Bms")
public class BmsController {
    @Autowired
    BmsService bmsService;
    @Autowired
    private CosUntil cosUntil;
    @Autowired
    private UserService userService;
    @Autowired
    private IMailService iMailService;

    /**
     * 添加图书类别(名称) (可以按语言、方向等分类)
     *
     * @param categoryNameObject 类别(名称)
     * @return 是否成功
     */
    @PreAuthorize("hasAuthority('会长')")
    @PostMapping("/addCategory")
    SimpleJson addBmsCategory(@RequestBody CategoryName categoryNameObject) {
        bmsService.addBmsCategory(categoryNameObject.getCategoryName());
        return SimpleJson.SUCCESS;
    }

    /**
     * 修改图书类别(名称)
     *
     * @param updateCategory 修改类别(名称请求)
     * @return 原编号返回false
     */
    @PreAuthorize("hasAuthority('会长')")
    @PostMapping("/updateCategory")
    SimpleJson updateBmsCategory(@RequestBody UpdateCategory updateCategory) {
        boolean flag = bmsService.updateBmsCategory(updateCategory.getOldCategoryName(), updateCategory.getNewCategoryName());
        return flag ? SimpleJson.SUCCESS : new SimpleJson(1, "原类别名称不存在 或 新类别名称已存在");
    }

    /**
     * 展示所有类别(名称)
     *
     * @return 所有类别的名称
     */
    @PreAuthorize("hasAuthority('游客')")
    @GetMapping("/getAllCategory")
    SimpleJson getAllCategory() {
        List<String> allCategory = bmsService.getAllCategory();
        return new SimpleJson(0, "成功", allCategory);
    }

    @PreAuthorize("hasAuthority('旧管理员')")
    @PostMapping("/addNewBook")
    public SimpleJson addNewBook(@RequestParam("bookImage") MultipartFile bookImage,
                                 @RequestParam("bmsBookName") String bmsBookName,
                                 @RequestParam("bmsBookIntroduction") String bmsBookIntroduction,
                                 @RequestParam("bmsBookOwner") String bmsBookOwner,
                                 @RequestParam("bmsBookPrice") String bmsBookPrice,
                                 @RequestParam("bmsCategory") String[] bmsCategory) {
        //进行合理性的验证

        if (!StringUtils.hasText(bmsBookName) || bookImage == null || !StringUtils.hasText(bmsBookOwner) || !StringUtils.hasText(bmsBookIntroduction) || !StringUtils.hasText(bmsBookPrice)) {
            return new SimpleJson(1, "您有信息为空，请检查，添加失败");
        }

        if (bmsCategory == null || bmsCategory.length == 0) {
            return new SimpleJson(1, "请给定书籍类型");
        }

        Double bookPrice;
        try {
            bookPrice = Double.parseDouble(bmsBookPrice);
        } catch (Exception e) {
            return new SimpleJson(1, "价格不符合规范,添加失败", null);
        }
        if (userService.getUserByUserName(bmsBookOwner) == null) {
            return new SimpleJson(1, "检查到错误书籍所属人，添加失败");
        }

        String originalFilename = bookImage.getOriginalFilename();


        assert originalFilename != null;
        if (!originalFilename.endsWith(".png") && !originalFilename.endsWith(".jpg")) {
            return new SimpleJson(1, "图片格式不正确，请为.png 或 .jpg，添加失败", null);
        }
        //以上完成了验证部分

        //解决文件覆盖问题
        String imageName = UUID.randomUUID() + "_" + originalFilename;

        //将图片保存到 腾讯云cos , 得到图片存储在 cos中的url

        String cosUrl;
        try {
            cosUrl = cosUntil.getCosUrl(bookImage, "SapImage/book/" + CommonUtils.getTimeDirectory() + "/" + imageName);
        } catch (IOException e) {
            return new SimpleJson(5, e.getMessage());
        }

        //将新书信息封装到一个 SapBmsBook 对象中
        SapBmsBook sapBmsBook = new SapBmsBook();
        //设置书名
        sapBmsBook.setBmsBookName(bmsBookName);
        //设置价格
        sapBmsBook.setBmsBookPrice(bookPrice);
        //设置图片路径
        sapBmsBook.setBmsBookImage(cosUrl);
        //设置所属人
        sapBmsBook.setBmsBookOwner(bmsBookOwner);
        //设置介绍
        sapBmsBook.setBmsBookIntroduction(bmsBookIntroduction);
        //设置书籍类型
        sapBmsBook.setBmsCategory(Arrays.asList(bmsCategory));

        //验证一下信息
        System.out.println(sapBmsBook);

        //进行了事务处理
        try {
            return bmsService.addBookInsertToBookTableAndBmsClassification(sapBmsBook);
        } catch (Exception e) {
            String exceptionMessage = e.getMessage();
            if ("未知名书籍类型，添加失败".equals(exceptionMessage)) {
                return new SimpleJson(1, exceptionMessage);
            } else {
                return new SimpleJson(5, "服务器未知异常，请稍后再试");
            }
        }

    }

    /**
     * 填充管理员表
     * 清除原表中数据，将当前(副)部长及以上职位用户加入管理表作为备用管理员，默认情况下刚更新管理表时只有会长直接是管理员
     *
     * @return 是否成功 (采用事务，失败会回滚)
     */
    @PreAuthorize("hasAuthority('会长')")
    @GetMapping("/fillManagerTable")
    SimpleJson fillBmsManagerTable() {
        String userForToken = JwtUtil.getUserForToken();
        String presidentUserName = userService.getPresidentUsername();
        if (!presidentUserName.equals(userForToken)) {
            //只允许会长使用
            return new SimpleJson(1, "权限不足");
        }
        try {
            bmsService.fillBmsManagerTable();
        } catch (Exception e) {
            return SimpleJson.FAILURE;
        }
        return SimpleJson.SUCCESS;
    }

    /**
     * 获取所有(备用/正式)管理员信息
     * (结果按职务对应的id和学号排序)
     *
     * @return (备用 / 正式)管理员信息列表
     */
    @PreAuthorize("hasAuthority('旧管理员')")
    @GetMapping("/getAllManagers")
    SimpleJson getBmsManagerVos() {
        List<BmsManagerVo> bmsManagerVos = bmsService.getBmsManagerVos();
        return new SimpleJson(0, "成功", bmsManagerVos);
    }

    /**
     * 设置让该(备用)管理员负责管理
     *
     * @param managerUsername 管理员学号
     * @return Json
     */
    @PreAuthorize("hasAuthority('会长')")
    @PostMapping("/setTheManagerToBeResponsible")
    SimpleJson setTheManagerToBeResponsible(@RequestBody ManagerUsername managerUsername) {
        return bmsService.setTheManagerToBeResponsible(managerUsername.getUsername());
    }

    /**
     * 撤销该(正式)管理员的管理职责
     *
     * @param managerUsername 管理员学号
     * @return Json
     */
    @PreAuthorize("hasAuthority('会长')")
    @PostMapping("/setTheManagerTeBeNotResponsible")
    SimpleJson setTheManagerTeBeNotResponsible(@RequestBody ManagerUsername managerUsername) {
        return bmsService.setTheManagerTeBeNotResponsible(managerUsername.getUsername());
    }

    /**
     * 获取所有书籍的信息
     *
     * @return 所有书籍的信息
     */
    @PreAuthorize("hasAuthority('游客')")
    @GetMapping("/getAllBookInformation")
    public SimpleJson getAllBookInformation() {
        return bmsService.getAllBookInformation();
    }

    /**
     * 根据类别查询书籍信息
     *
     * @param classification 类别
     * @return 书籍信息
     */
    @PreAuthorize("hasAuthority('游客')")
    @GetMapping("/getBookInformationByClass")
    public SimpleJson getBookInformation(@RequestParam String classification) {
        return bmsService.getBookInformation(classification);
    }

    /**
     * 查询当前所有(正式)管理员
     *
     * @return 当前具有管理职责的管理员(正式管理员)信息的集合
     */
    @PreAuthorize("hasAuthority('游客')")
    @GetMapping("/getResponsibleManagers")
    SimpleJson getResponsibleManagers() {
        List<BmsManagerVo> bmsResponsibleManagerVos = bmsService.getBmsResponsibleManagerVos();
        return new SimpleJson(0, "成功", bmsResponsibleManagerVos);
    }

    @PreAuthorize("hasAuthority('旧管理员')")
    @PutMapping("/updateBookInformation")
    SimpleJson updateBookInformation(@RequestBody SapBmsBook sapBmsBook) {
        try {
            return bmsService.updateBookInformation(sapBmsBook);
        } catch (Exception e) {
            return new SimpleJson(5, "数据库或服务器错误：" + e.getMessage());
        }
    }


    /**
     * 申请借阅
     *
     * @param borrow 申请借阅信息
     */
    @PreAuthorize("hasAuthority('正式成员')")
    @PostMapping("/applyBorrow")
    SimpleJson applyBorrow(@RequestBody ApplyBorrow borrow) {
        //用户名(学号)
        String username = JwtUtil.getUserForToken();
        //生成申请记录
        SapBmsBorrow sapBmsBorrow = new SapBmsBorrow(borrow.getBmsBookId(), username, borrow.getExpectedReturnTime());
        //插入申请借阅信息 发送邮件
        return bmsService.applyBorrow(username, sapBmsBorrow);
    }

    /**
     * 申请归还 / 赔偿
     *
     * @param applyReturn 申请归还/赔偿信息
     * @return Json
     */
    @PreAuthorize("hasAuthority('正式成员')")
    @PostMapping("/applyReturn")
    SimpleJson applyReturn(@RequestBody ApplyReturn applyReturn) {
        //申请人用户名(学号)
        String username = JwtUtil.getUserForToken();
        return bmsService.applyReturn(username, applyReturn.getBorrowId(), applyReturn.getBorrowFlag());
    }

    /**
     * 查询自己所有的借阅信息
     *
     * @return 自己的借阅信息
     */
    @PreAuthorize("hasAuthority('正式成员')")
    @GetMapping("/getUserBorrowInformation")
    SimpleJson getUserBorrowInformation() {
        return bmsService.getUserBorrowInformation();
    }

    /**
     * 查询所有的借阅信息
     *
     * @return 所有的借阅信息
     */
    @PreAuthorize("hasAuthority('游客')")
    @GetMapping("/getAllBorrowInformation")
    SimpleJson getAllBorrowInformation() {
        return bmsService.getAllBorrowInformation();
    }

    /**
     * 查询未审核的借阅信息
     * (状态为 ‘申请中’的记录)
     *
     * @return 借阅记录
     */
    @PreAuthorize("hasAuthority('管理员')")
    @GetMapping("/getRecordOfBorrowingApplication")
    SimpleJson getRecordOfBorrowingApplication() {
        return new SimpleJson(0, "成功", bmsService.getRecordOfBorrowingApplication());
    }

    /**
     * 查询未审核的归还/赔偿信息
     * (状态为 ‘申请归还’或'申请赔偿' 的记录)
     *
     * @return 借阅记录
     */
    @PreAuthorize("hasAuthority('管理员')")
    @GetMapping("/getRecordOfReturningApplication")
    SimpleJson getRecordOfReturningApplication() {
        return new SimpleJson(0, "成功", bmsService.getRecordOfReturningApplication());
    }

    @PreAuthorize("hasAuthority('管理员')")
    @PutMapping("/checkBorrowInformation")
    SimpleJson checkBorrowInformation(@RequestBody BmsBorrowVo bmsBorrowVo) {
        try {
            return bmsService.checkBorrowInformation(bmsBorrowVo);
        } catch (Exception e) {
            User president = userService.getPresidentUserInfo();
            String content = "书籍申请审核时发生的错误信息：\n" + e.getMessage() + "\n请及时排查错误";
            try {
                iMailService.sendSimpleMail(president.getQq() + "@qq.com", "书籍申请审核异常", content);
                userService.sendNoticeAuto(new NoticeDto(president.getUsername(), content, null));
            } catch (Exception ex) {
                return new SimpleJson(5, "异常信息：" + e);
            }
            iMailService.sendSimpleMail(president.getQq() + "@qq.com", "书籍申请审核异常", content);
            userService.sendNoticeAuto(new NoticeDto(president.getUsername(), content, null));
            return new SimpleJson(5, "异常信息：" + e);
        }
    }

    /**
     * 审核归还消息
     *
     * @return Json
     */
    @PreAuthorize("hasAuthority('管理员')")
    @GetMapping("/checkBookReturnInformation")
    SimpleJson checkBookReturnInformation(@RequestParam("borrowId") Integer borrowId) {
        try {
            if (borrowId == null) {
                return new SimpleJson(1, "无效的借阅编号");
            }
            BmsBorrowVo bmsBorrowVo = new BmsBorrowVo();
            bmsBorrowVo.setBmsBorrowId(borrowId);
            return bmsService.checkBookReturnInformation(bmsBorrowVo);
        } catch (Exception e) {
            User president = userService.getPresidentUserInfo();
            String content = "书籍归还审核时发生的错误信息：\n" + e.getMessage() + "\n请及时排查错误";
            try {
                iMailService.sendSimpleMail(president.getQq() + "@qq.com", "书籍归还审核异常", content);
                userService.sendNoticeAuto(new NoticeDto(president.getUsername(), content, null));
            } catch (Exception ex) {
                return new SimpleJson(5, "异常信息：" + e);
            }
            return new SimpleJson(5, "异常信息：" + e);
        }
    }

    /**
     * 手动修改借阅状态
     *
     * @param modifyManually 修改借阅状态请求参数
     * @return Json
     */
    @PreAuthorize("hasAuthority('管理员')")
    @PostMapping("/modifyBorrowStateManually")
    SimpleJson modifyBorrowStateManually(@RequestBody ModifyManually modifyManually) {
        Integer borrowId = modifyManually.getBorrowId();
        String state = modifyManually.getState();
        //事务处理
        SimpleJson json;
        try {
            json = bmsService.modifyBorrowStateManually(borrowId, state);
        } catch (Exception e) {
            return new SimpleJson(5, "事务异常，操作失败");
        }
        return json;
    }

    /**
     * 获取书籍类别及对应其书籍数量
     *
     * @return Josn(书籍类别及其对应书籍数量视图)
     */
    @PreAuthorize("hasAuthority('游客')")
    @GetMapping("/getCategoryWithBookNumber")
    SimpleJson getCategoryWithBookNumber() {
        return new SimpleJson(0, "成功", bmsService.getCategoryWithBookNumber());
    }

    /**
     * 取消借阅申请
     *
     * @param cancel 记录编号
     * @return Json
     */
    @PreAuthorize("hasAuthority('正式成员')")
    @PostMapping("/cancelBorrowApplication")
    public SimpleJson cancelBorrowApplication(@RequestBody CancelBorrow cancel) {
        if (cancel.getBmsBorrowId() == null) {
            return new SimpleJson(7, "请输入参数");
        }
        return bmsService.cancelBorrowOrReturnApplication(cancel.getBmsBorrowId(), 0);
    }

    /**
     * 取消归还申请
     *
     * @param cancel 记录编号
     * @return Json
     */
    @PreAuthorize("hasAuthority('正式成员')")
    @PostMapping("/cancelReturnApplication")
    public SimpleJson cancelReturnApplication(@RequestBody CancelBorrow cancel) {
        if (cancel.getBmsBorrowId() == null) {
            return new SimpleJson(7, "请输入参数");
        }
        return bmsService.cancelBorrowOrReturnApplication(cancel.getBmsBorrowId(), 1);
    }

    /**
     * 获取每月借阅申请数量
     *
     * @return Json
     */
    @PreAuthorize("hasAuthority('游客')")
    @GetMapping("/getBorrowNumberEachMonthInThePastYear")
    public SimpleJson getBorrowNumberEachMonthInThePastYear() {
        return new SimpleJson(0, "成功", bmsService.getBorrowNumberEachMonthInThePastYear());
    }
}
